package org.openkoala.koala.popup.javaclass.crud;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.openkoala.koala.deploy.curd.module.core.EntityModel;
import org.openkoala.koala.deploy.curd.module.core.FieldModel;
import org.openkoala.koala.deploy.curd.module.core.model.RelationFieldModel;
import org.openkoala.koala.deploy.curd.module.ui.Model;
import org.openkoala.koala.deploy.curd.module.ui.UIWidget;
import org.openkoala.koala.deploy.curd.module.ui.model.TabViewUI;
import org.openkoala.koala.deploy.curd.module.ui.model.ViewModel;
import org.openkoala.koala.deploy.curd.module.ui.view.RelativeReadOnlyView;

public class RelationViewComponent extends CrudComponent {
    
    private Composite parent;

	private Button add;
	private Button edit;
	private Button remove;

	private EntityModel entityModel;
    private ViewModel viewModel;
    
    private Tree fieldTree;
    private TreeItem selectedAssociationItem;
    
    RelationViewComponent(Composite parent, ViewModel viewModel, EntityModel entityModel) {
        this.parent = parent;
        this.viewModel = viewModel;
        this.entityModel = entityModel;
    }
    
    public Control createControl() {
        GridData gridData = new GridData(GridData.FILL_BOTH);
        GridLayout gridLayout = new GridLayout(2, false);
        
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayoutData(gridData);
        composite.setLayout(gridLayout);
        
        generateFieldTree(composite);
        generateOperationComposite(composite);
        
        return composite;
    }

	private void generateFieldTree(Composite parent) {
		GridData treeGridData = new GridData(GridData.FILL_VERTICAL);
		treeGridData.widthHint = 350;

		fieldTree = new Tree(parent, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);
		fieldTree.setLayoutData(treeGridData);
		fieldTree.setLinesVisible(true);
		fieldTree.setHeaderVisible(true);
		fieldTree.addSelectionListener(new FieldTreeListener());
		fieldTree.addListener(SWT.MouseDoubleClick, new FieldTreeDoubleClickListener());
		
		TreeColumn propertiesName = new TreeColumn(fieldTree, SWT.NONE);
		propertiesName.setText("属性名");
		propertiesName.setWidth(150);
		
		TreeColumn viewName = new TreeColumn(fieldTree, SWT.NONE);
		viewName.setText("显示名称");
		viewName.setWidth(150);
		
	    for (TabViewUI tabViewUI : viewModel.getTabs()) {
			TreeItem associationProperty = new TreeItem(fieldTree, SWT.NONE);
			associationProperty.setText(new String[]{tabViewUI.getRelationFieldModel().getName(), ""});
			associationProperty.setData(tabViewUI);

	    	for (UIWidget widget : tabViewUI.getListModel().getViews()) {
				TreeItem property = new TreeItem(associationProperty, SWT.NONE);
				property.setText(new String[]{widget.getExpress(), widget.getName()});
				property.setData(widget);
	    	}
	    }

		for (TreeItem treeItem : fieldTree.getItems()) {
			treeItem.setExpanded(true);
		}
		
	}
    
    private void generateOperationComposite(Composite parent) {
        GridLayout gridLayout = new GridLayout(1, false);
        GridData gridData = new GridData(GridData.FILL_BOTH);
        
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayout(gridLayout);
        composite.setLayoutData(gridData);
        
        GridData buttonGridDate = new GridData(GridData.FILL_HORIZONTAL);
        
        add = new Button(composite, SWT.PUSH);
        add.setText("添加");
        add.setData(CrudConstants.BUTTON_ADD);
        add.setLayoutData(buttonGridDate);
        add.addSelectionListener(new ButtonSelectionListener());
        
        edit = new Button(composite, SWT.PUSH);
        edit.setText("编辑");
        edit.setData(CrudConstants.BUTTON_EDIT);
        edit.setLayoutData(buttonGridDate);
        edit.addSelectionListener(new ButtonSelectionListener());
        edit.setEnabled(false);
        
        remove = new Button(composite, SWT.PUSH);
        remove.setText("删除");
        remove.setData(CrudConstants.BUTTON_REMOVE);
        remove.setLayoutData(buttonGridDate);
        remove.addSelectionListener(new ButtonSelectionListener());
        remove.setEnabled(false);
    }

	@Override
	public void addItem(UIWidget widget) {
		if (selectedAssociationItem != null) {
			TreeItem treeItem = new TreeItem(selectedAssociationItem, SWT.NONE);
			treeItem.setText(new String[]{widget.getExpress(), widget.getName()});
			treeItem.setData(widget);
		}
	}
	
	public void addItem(UIWidget widget, TabViewUI tabViewUI) {
		TreeItem treeItem = getTreeItemByData(tabViewUI);
		if (treeItem == null) {
			treeItem = new TreeItem(fieldTree, SWT.NONE);
			treeItem.setText(new String[]{tabViewUI.getRelationFieldModel().getName(), ""});
			treeItem.setData(tabViewUI);
		}
		
		TreeItem fieldTreeItem = new TreeItem(treeItem, SWT.NONE);
		fieldTreeItem.setText(new String[]{widget.getExpress(), widget.getName()});
		fieldTreeItem.setData(widget);
	}
	
	private TreeItem getTreeItemByData(TabViewUI tabViewUI) {
		for (TreeItem treeItem : fieldTree.getItems()) {
			if (treeItem.getData().equals(tabViewUI)) {
				return treeItem;
			}
		}
		return null;
	}
	
	@Override
	public void update(UIWidget oldWidget, UIWidget newWidget) {
		TreeItem treeItem = getTreeItemByWidget(oldWidget, fieldTree.getItems());
		treeItem.setText(new String[]{newWidget.getExpress(), newWidget.getName()});
	}
    
	@Override
	public void refresh(UIWidget widget) {
		update(widget, widget);
	}
	
	private TreeItem getTreeItemByWidget(UIWidget widget, TreeItem[] treeItems) {
		for (TreeItem treeItem : treeItems) {
			if (treeItem.getData().equals(widget)) {
				return treeItem;
			}
			if (treeItem.getItems().length > 0) {
				TreeItem theTreeItem = getTreeItemByWidget(widget, treeItem.getItems());
				if (theTreeItem != null) {
					return theTreeItem;
				}
			}
		}
		return null;
	}
	
	private void responseAddButton() {
		Map<FieldModel, List<FieldModel>> relationFieldModels = new HashMap<FieldModel, List<FieldModel>>();
		
		for (RelationFieldModel relationFieldModel : entityModel.getRelationFieldModel()) {
			TabViewUI tabViewUI = CrudUtils.getTabViewUiFromModel(relationFieldModel, viewModel);
			EntityModel relationFielEntityModel = relationFieldModel.getRelationModel().getEntityModel();
			List<FieldModel> fieldModels = new ArrayList<FieldModel>(relationFielEntityModel.getFields());
			fieldModels.removeAll(relationFielEntityModel.getIDFieldModel());
			fieldModels.removeAll(relationFielEntityModel.getRelationFieldModel());
			fieldModels.removeAll(relationFielEntityModel.getObjectValueFieldModel());
			List<FieldModel> fieldModelsToAdd = new ArrayList<FieldModel>();
			
			if (tabViewUI == null) {
				fieldModelsToAdd.addAll(fieldModels);
				relationFieldModels.put(relationFieldModel, fieldModelsToAdd);
				continue;
			}
			
			for (FieldModel fieldModel : fieldModels) {
				if (!CrudUtils.fieldNameIsInModel(fieldModel.getName(), tabViewUI.getListModel())) {
					fieldModelsToAdd.add(fieldModel);
				}
			}
			
			if (!fieldModelsToAdd.isEmpty()) {
				relationFieldModels.put(relationFieldModel, fieldModelsToAdd);
			}
		}
		
		if (relationFieldModels.isEmpty()) {
			MessageDialog.openInformation(parent.getShell(), "提示", "没有可添加的属性");
			return;
		}
		
		RelationFieldConfigDialog dialog = 
				RelationFieldConfigDialog.createInstance(parent.getShell(), this, relationFieldModels, viewModel, entityModel);
		dialog.open();
	}
	
	private void responseEditButton(UIWidget widget, Model model, EntityModel theEntityModel) {
		if (widget instanceof RelativeReadOnlyView) {
			EditFieldConfigurationDialog dialog = 
					EditFieldConfigurationDialog.createByUpdateAssociationField(parent.getShell(), this, 
							widget, model, createAssociationFieldModels((RelativeReadOnlyView) widget, theEntityModel));
			dialog.open();
			return;
		}
		
		EditFieldConfigurationDialog dialog = EditFieldConfigurationDialog.createByUpdateField(parent.getShell(), this, widget, model);
		dialog.open();
	}
	
	private void removeUIWidget(TreeItem treeItem, Model model) {
		model.getViews().remove((UIWidget) treeItem.getData());
		treeItem.dispose();
	}
	
	private void removeTabViewUI(TreeItem treeItem) {
		viewModel.getTabs().remove((TabViewUI) treeItem.getData());
		treeItem.dispose();
	}
	
	private List<FieldModel> createAssociationFieldModels(RelativeReadOnlyView relativeReadOnlyView, EntityModel associationEntityModel) {
		List<FieldModel> results = new ArrayList<FieldModel>();
		
		RelationFieldModel relationFieldModel = 
				(RelationFieldModel) CrudUtils.getFieldModelByName(relativeReadOnlyView.getRelative(), associationEntityModel.getFields());
		EntityModel entityModel = relationFieldModel.getRelationModel().getEntityModel();
		List<FieldModel> fieldModels = new ArrayList<FieldModel>(entityModel.getFields());
		fieldModels.remove(entityModel.getObjectValueFieldModel());
		fieldModels.remove(entityModel.getRelationFieldModel());
		
		for (FieldModel fieldModel : fieldModels) {
			results.add(fieldModel);
		}
		return results;
	}
	
    private class ButtonSelectionListener implements SelectionListener {

		@Override
		public void widgetDefaultSelected(SelectionEvent e) {
		}

		@Override
		public void widgetSelected(SelectionEvent event) {
			Button button = (Button) event.getSource();
			
        	if (button.getData().equals(CrudConstants.BUTTON_ADD)) {
        		responseAddButton();
				return;
			}

        	TreeItem treeItem = (TreeItem) fieldTree.getSelection()[0];
        	TreeItem parentItem = treeItem.getParentItem();
        	
        	if (parentItem == null) {
        		if (button.getData().equals(CrudConstants.BUTTON_REMOVE)) {
        			removeTabViewUI(treeItem);
        		}
				return;
			}
        	
        	TabViewUI tabViewUI = null;
        	Model model = null;
        	EntityModel theEntityModel = null;
        	
			tabViewUI = (TabViewUI) parentItem.getData();
			model = tabViewUI.getListModel();
			selectedAssociationItem = parentItem;
			theEntityModel = tabViewUI.getRelationFieldModel().getRelationModel().getEntityModel();
        	
            UIWidget widget = (UIWidget) treeItem.getData();
			if (button.getData().equals(CrudConstants.BUTTON_EDIT)) {
				responseEditButton(widget, model, theEntityModel);
			}
			
			if (button.getData().equals(CrudConstants.BUTTON_REMOVE)){
				removeUIWidget(treeItem, model);
			}
		}
    }

    private class FieldTreeListener implements SelectionListener {
        @Override
        public void widgetSelected(SelectionEvent event) {
			edit.setEnabled(true);
			remove.setEnabled(true);
        }

        @Override
        public void widgetDefaultSelected(SelectionEvent event) {
        }
    }
    
    private class FieldTreeDoubleClickListener implements Listener {
		@Override
		public void handleEvent(Event event) {
			TreeItem treeItem = (TreeItem) fieldTree.getSelection()[0];
        	TreeItem parentItem = treeItem.getParentItem();
        	if (parentItem == null) {
				return;
			}
			selectedAssociationItem = parentItem;

        	TabViewUI tabViewUI = (TabViewUI) parentItem.getData();
        	Model model = tabViewUI.getListModel();
			EntityModel theEntityModel = tabViewUI.getRelationFieldModel().getRelationModel().getEntityModel();
			
			UIWidget widget = (UIWidget) treeItem.getData();
			responseEditButton(widget, model, theEntityModel);
		}
    }

}
